#include <amber/helper.hpp>
#include <fstream>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <string>

void cropImages(const std::string& imageListFileName, const std::string& outputDir, int32_t rows, int32_t cols);
cv::Mat cropImage(cv::Mat image, int startRow, int startCols, int rows, int cols);

int main(int argc, char** argv)
{
    if (argc < 3) {
        std::cerr << "Invalid arguments" << std::endl;

        std::cout << "This application crops the images to 32x32 blocks\n"
                     "Usage:\n"
                     "    crop-images input_image_file_list output_dir\n"
                  << std::endl;
        return EXIT_FAILURE;
    }

    cropImages(argv[1], argv[2], 32, 32);

    return 0;
}

// 将一张图片切割为32X32的小图
void cropImages(const std::string& imageListFileName, const std::string& outputDir, int32_t rows, int32_t cols)
{
    int count = 0;
    // 打开图片列表文件
    std::vector<std::string> imageListFile = amber::listFiles(imageListFileName);
    for (auto imageFilePath : imageListFile) {

        // 读取图像
        cv::Mat image = cv::imread(imageFilePath);
        int imageRows = image.rows; // 1024
        int imageCols = image.cols; // 768

        std::cout << "crop image: " << imageFilePath << std::endl;
        // 逐个切图（每次切rows*cols大小的图片）
        // 遍历行
        for (int row = 0; row < imageRows; row += rows) {
            // 遍历列
            for (int col = 0; col < imageCols; col += cols) {
                // 截图
                cv::Mat croppedImage = cropImage(image, row, col, rows, cols);

                // 保存截图
                std::string croppedFileName = outputDir + "/" + std::to_string(count) + ".bmp";
                std::cout << "  Write cropped image: " << croppedFileName << std::endl;
                cv::imwrite(croppedFileName, croppedImage);
                ++count;
            }
        }
    }
}

// 从指定位置截取rows * cols大小的图片
cv::Mat cropImage(cv::Mat image, int startRow, int startCol, int rows, int cols)
{
    int imageRows = image.rows;
    int imageCols = image.cols;

    // 如果原图中能截取出rows*cols的图，则直接返回该部分切图
    if (startRow + rows < imageRows && startCol + cols < imageCols) {
        return cv::Mat(image, cv::Range(startRow, startRow + rows), cv::Range(startCol, startCol + cols));
    }

    // 否则说明到达图片边缘
    // 创建一个rows*cols的图，全部填0
    cv::Mat croppedImage = cv::Mat::zeros(rows, cols, CV_8UC3);
    uchar* croppedImageData = croppedImage.data;
    uchar* imageData = image.data;
    int realRows = std::min(imageRows - startRow, rows);
    int realCols = std::min(imageCols - startCol, cols);

    // 将原图能切出的所有像素复制到目标切图的左上角。剩余部分保留0。
    for (int row = 0; row < realRows; ++row) {
        for (int col = 0; col < realCols; ++col) {
            int croppedImageOffset = (row * cols + col) * 3;
            int imageOffset = ((startRow + row) * imageCols + startCol + col) * 3;
            croppedImageData[croppedImageOffset] = imageData[imageOffset];
            croppedImageData[croppedImageOffset + 1] = imageData[imageOffset + 1];
            croppedImageData[croppedImageOffset + 2] = imageData[imageOffset + 2];
        }
    }

    return croppedImage;
}
